/***********************************************************
 * File Name    : HeartRateCalibrator.c
 * Description  : 校准心率
 * Author       : 
 * Create Date  : 
 * Last Modified: 
 * Version      : 
 * Note         : 
 ***********************************************************/
#include "HeartRateCalibrator.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

static HeartRateCalibrator* instance = NULL;

HeartRateCalibrator* HeartRateCalibrator_getInstance() {
    if (instance == NULL) {
        instance = (HeartRateCalibrator*)malloc(sizeof(HeartRateCalibrator));
        instance->historyIndex = 0;
        instance->historyCount = 0;
        instance->consecutiveOverThreshold = 0;
        instance->currentMaxAllowedChange = DEFAULT_MAX_ALLOWED_CHANGE;
        instance->zeroCount = 0;
    }
    return instance;
}

void addToHistory(HeartRateCalibrator* calibrator, int heartRate) {
    calibrator->heartRateHistory[calibrator->historyIndex] = heartRate;
    calibrator->historyIndex = (calibrator->historyIndex + 1) % SMOOTHING_WINDOW_SIZE;
    if (calibrator->historyCount < SMOOTHING_WINDOW_SIZE) {
        calibrator->historyCount++;
    }
}

int getLastHeartRate(HeartRateCalibrator* calibrator) {
    if (calibrator->historyCount == 0) {
        //fprintf(stderr, "没有历史心率数据\n");
        return 0;
    }
    int lastIndex = (calibrator->historyIndex - 1 + SMOOTHING_WINDOW_SIZE) % SMOOTHING_WINDOW_SIZE;
    return calibrator->heartRateHistory[lastIndex];
}

int calculateSmoothedValue(HeartRateCalibrator* calibrator) {
    if (calibrator->historyCount == 0) {
        //fprintf(stderr, "没有历史心率数据\n");
        return 0;
    }
    int sum = 0;
    for (int i = 0; i < calibrator->historyCount; i++) {
        sum += calibrator->heartRateHistory[i];
    }
    return sum / calibrator->historyCount;
}

int HeartRateCalibrator_calibrate(HeartRateCalibrator* calibrator, int rawHeartRate) {
    // 检查是否为0值
    if (rawHeartRate == 0) {
        calibrator->zeroCount++;
        // 如果连续三次为0，则重置心率数据
        if (calibrator->zeroCount >= 3) {
            HeartRateCalibrator_reset(calibrator);
            return 0;
        }
    } else {
        calibrator->zeroCount = 0; // 重置计数器
    }

    // 第一步：限制在生理范围内
    int clamped = rawHeartRate;
    if (clamped < DEFAULT_MIN_HEART_RATE) {
        clamped = DEFAULT_MIN_HEART_RATE;
    } else if (clamped > DEFAULT_MAX_HEART_RATE) {
        clamped = DEFAULT_MAX_HEART_RATE;
    }

    // 如果没有历史数据，直接返回限制后的值
    if (calibrator->historyCount == 0) {
        addToHistory(calibrator, clamped);
        return clamped;
    }

    // 获取上一次的心率值
    int lastRate = getLastHeartRate(calibrator);

    // 检查当前心率变化是否超过阈值
    bool isOverThreshold = abs(clamped - lastRate) > calibrator->currentMaxAllowedChange;

    // 更新连续超过阈值的计数器
    if (isOverThreshold) {
        calibrator->consecutiveOverThreshold++;

        // 如果连续三次超过阈值，放宽限制
        if (calibrator->consecutiveOverThreshold >= 3) {
            calibrator->currentMaxAllowedChange = RELAXED_MAX_ALLOWED_CHANGE;
        }
    } else {
        // 重置计数器并恢复默认限制
        calibrator->consecutiveOverThreshold = 0;
        calibrator->currentMaxAllowedChange = DEFAULT_MAX_ALLOWED_CHANGE;
    }

    // 第二步：限制突变（使用当前的最大允许变化值）
    int bounded;
    if (isOverThreshold) {
        // 如果变化过大，限制变化幅度
        if (clamped > lastRate) {
            bounded = lastRate + calibrator->currentMaxAllowedChange;
        } else {
            bounded = lastRate - calibrator->currentMaxAllowedChange;
        }
        // 再次限制在生理范围内
        if (bounded < DEFAULT_MIN_HEART_RATE) {
            bounded = DEFAULT_MIN_HEART_RATE;
        } else if (bounded > DEFAULT_MAX_HEART_RATE) {
            bounded = DEFAULT_MAX_HEART_RATE;
        }
    } else {
        bounded = clamped;
    }

    // 第三步：平滑处理 (移动平均)
    addToHistory(calibrator, bounded);
    int smoothed = calculateSmoothedValue(calibrator);

    return smoothed;
}

void HeartRateCalibrator_reset(HeartRateCalibrator* calibrator) {
    calibrator->historyIndex = 0;
    calibrator->historyCount = 0;
    calibrator->consecutiveOverThreshold = 0;
    calibrator->currentMaxAllowedChange = DEFAULT_MAX_ALLOWED_CHANGE;
    calibrator->zeroCount = 0; // 重置计数器
}

int HeartRateCalibrator_getCurrentMaxAllowedChange(HeartRateCalibrator* calibrator) {
    return calibrator->currentMaxAllowedChange;
}

void HeartRateCalibrator_destroy(HeartRateCalibrator* calibrator) {
    free(calibrator);
    if (calibrator == instance) {
        instance = NULL;
    }
}
